-- UIGameBoard
-- Create by cheny3 Oct/13/2015
-- 游戏公告界面

UIGameBoard = class("UIGameBoard",function()
    return cc.Layer:create()
end)

function UIGameBoard.create(data)
    return UIGameBoard.new(data);
end

-- 内部函数
local resize;
local PER_LINE_WORD_COUNT = 21;

-- 构造函数
function UIGameBoard:ctor(data)
    self:setName("UIGameBoard");

    -- 初始化
    local node = cc.CSLoader:createNode("layout/setting/GameBoard.csb");
    self:addChild(node);
    self.node = node;

    if not _G["gameScene"] then
        self:setLocalZOrder(UIMgr.BONUS_NOTIFY_ZORDER + 1);
    end

    -- 获取要显示的说明内容
    self.data = data;
    self.boardId = data["boardId"];

    -- 标记已经阅读过
    self:setAlreadyRead();

    -- 重绘
    self:redraw();

    -- 注册点击事件
    self:registerTouchEvent();

    -- 注册事件处理回调函数
    self:registerEventCallback();

    -- 适配
    resize(node);
end

-- 重绘
function UIGameBoard:redraw()
    -- 标题
    local title1Label = findChildByName(self.node, "CT/title1");
    local title2Label = findChildByName(self.node, "CT/title2");
    local data = self.data;

    -- 标题1公告标题
    title1Label:setString(data["title"]);

    -- 标题2公告发布时间
    title2Label:setString(data["subhead"]);

    TextStyleM.setTitleStyle(title1Label);
    TextStyleM.setSubheadStyle(title2Label);

    -- 内容
    local contentLabel = findChildByName(self.node, "CT/scroll_view/content");
    local contentText = data["content"];
    contentLabel:setPositionX(14);

    -- 不同语言版本的 给玩家一封信/Peter的一封信 需要根据字号的统一缩放增加下每行的字数
    local locFix = 1;
    if data["boardId"] == -1 or data["boardId"] == -3 then
        locFix = getLocFontSizeMulti();
    end

    TextStyleM.setTextStyle(contentLabel, TextStyleM.TEXT_SIZE_SMALL2,
        TextStyleM.TEXT_COLOR_DARK_BROWN, false, -1, nil, nil, PER_LINE_WORD_COUNT / locFix);
    -- 先赋予文字/行间距用于计算高度
    contentLabel:getVirtualRenderer():setLineHeight(TextStyleM.TEXT_LINE_HIGHT_MIDDLE);
    contentLabel:setString(extractString(contentText));

    -- 设置容器高度
    local scrollview = findChildByName(self.node, "CT/scroll_view");
    local height = math.max(getRealContentSize(contentLabel).height, scrollview:getInnerContainerSize().height);
    contentLabel:setPositionY(height - 15);
    scrollview:setInnerContainerSize(cc.size(scrollview:getInnerContainerSize().width, height));

    -- 如果是制作人名单，那么特殊处理下
    if data["boardId"] == -2 then
        local labelRight = findChildByName(self.node, "CT/scroll_view/content_right");

        local text = GameBoardM.getSecondGameBoard()["name"];
        TextStyleM.setTextStyle(labelRight, TextStyleM.TEXT_SIZE_SMALL2,
            TextStyleM.TEXT_COLOR_DARK_BROWN, false, -1, nil, nil, PER_LINE_WORD_COUNT);
        -- 先赋予文字/行间距用于计算高度
        labelRight:getVirtualRenderer():setLineHeight(TextStyleM.TEXT_LINE_HIGHT_MIDDLE);
        labelRight:setString(text);
        labelRight:setPositionY(height - 15);
    end

    -- 绘制横线
    local lineNode;
    if not _G["gameScene"] then
        lineNode = ccui.ImageView:create(getSettingIconPath("system", "line"));
    else
        lineNode = ccui.ImageView:create("images/ui/setting/line.png");
    end
    local linePosY = height - 10;
    while linePosY > 0 do
        local line = lineNode:clone();
        line:setPosition(250, linePosY);
        scrollview:addChild(line);
        linePosY = linePosY - TextStyleM.TEXT_LINE_HIGHT_MIDDLE;
    end

    -- 添加滚动条
    UIIndicator.attach(scrollview);
    local indicator = scrollview:getParent():getChildByName("UIIndicator");
    indicator:setPositionX(indicator:getPositionX() + 2);

    -- 文字效果
    applyString(contentLabel, contentText, nil, nil, TextStyleM.TEXT_LINE_HIGHT_MIDDLE, PER_LINE_WORD_COUNT / locFix);

    -- 添加了特殊节点
    local specialNode = self:addSpecialNode();
    if specialNode then
        scrollview:addChild(specialNode);
        local posX = getRealContentSize(scrollview).width / 2;
        specialNode:setPosition(cc.p(posX, 25));
    end

    -- 如果系统设置界面开着则不显示 更多 按钮
    local btnMore = findChildByName(self.node, "BT/btn_more");
    if self:needShowMore() then
        btnMore:setVisible(true);
    else
        btnMore:setVisible(false);
    end
end

-- 是否需要显示更多
function UIGameBoard:needShowMore()
    if not _G["gameScene"] then
        require "game/ui/form/setting/UISystemSetting";
        local uiSystemSetting = UIMgr.getCurrentScene():getFormByName("UISystemSetting");
        local uiLoginSetting = UIMgr.getCurrentScene():getFormByName("UILoginSetting");
        local uiCommentDesk = UIMgr.getCurrentScene():getFormByName("UICommentDesk");
        if uiSystemSetting or uiLoginSetting or uiCommentDesk or not self.boardId
            or (type(self.boardId) == "number" and (self.boardId <= 0 and self.boardId ~= -1)) then
            return false;
        else
            return true;
        end
    end
    return false;
end

-- 标记已经阅读过
function UIGameBoard:setAlreadyRead()
    if type(self.boardId) == "number" and self.boardId ~= 0 then
        -- 通知阅读过了该公告了
        GameBoardM.addUserReadRecord(self.boardId);
    elseif type(self.boardId) == "string" then
        -- WEB拉取的本地留存
        GameBoardM.addUserReadRecord(self.boardId);
    end
end

-- 是否需要显示下一封
function UIGameBoard:needShowNext()
    if self:needShowMore() then
        -- 检查公告信息/未完成新手指引不弹出
        local boardId = GameBoardM.getLastNotReadId();

        if (tonumber(boardId) > 0 or tonumber(boardId) == -1)
            and AlchemyWorkshopM.isAllGuideFinished() then
            -- 有公告需要显示
            return boardId;
        end
    end
    return false;
end

-- 注册点击事件
function UIGameBoard:registerTouchEvent()
    local btnBack = findChildByName(self.node, "BT/btn_back");
    local showNext = self:needShowNext();
    local function onBackClick(sender, eventType)
        if eventType == ccui.TouchEventType.ended then
            -- 关闭当前界面
            if not _G["gameScene"] then
                AudioM.playFx("button_return");
                if showNext then
                    -- 显示下一封
                    -- 必须显示锁屏界面
                    -- 否则会经过大地图界面，弹出炼金提示
                    wait(0.5);
                    UIMgr.getCurrentScene():removeFormByName("UIGameBoard");
                    showGameBoard(showNext);
                else
                    UIMgr.getCurrentScene():removeFormByName("UIGameBoard");
                    uiSystemSetting = UIMgr.getCurrentScene():getFormByName("UISystemSetting");
                    if uiSystemSetting then
                        -- 播放弹出效果
                        uiSystemSetting:playFormEffect();
                    end
                end
            else
                _G["gameScene"]:removeFormByName("UIGameBoard");
                -- 开始自动更新
                clearMyRequire();
                enterAutoPatchScene();
            end
        end
    end
    if not _G["gameScene"] then
        AddBackEventHandler(self, btnBack, onBackClick);
    else
        btnBack:addTouchEventListener(onBackClick);
    end
    TextStyleM.setTextStyle(btnBack, TextStyleM.TEXT_SIZE_MIDDLE, TextStyleM.TEXT_COLOR_BROWN_YELLOW, true);
    if showNext then
        btnBack:setTitleText(getLocStr("btn_text_next"));
    else
        btnBack:setTitleText(getLocStr("btn_text_back"));
    end

    local btnMore = findChildByName(self.node, "BT/btn_more");
    local function onMoreClick(sender, eventType)
        if eventType == ccui.TouchEventType.ended then
            AudioM.playFx("button_click");
            -- 必须先打开公告界面再关闭当前界面
            -- 否则会经过大地图界面，弹出炼金提示
            -- 打开公告界面
            require "game/ui/form/setting/UISystemSetting";
            local uiSystemSetting = UISystemSetting.create(2);
            UIMgr.getCurrentScene():addForm(uiSystemSetting);

            -- 关闭当前界面
            UIMgr.getCurrentScene():removeFormByName("UIGameBoard");
        end
    end
    btnMore:addTouchEventListener(onMoreClick);
    TextStyleM.setTextStyle(btnMore, TextStyleM.TEXT_SIZE_MIDDLE, TextStyleM.TEXT_COLOR_BROWN_YELLOW, true);
    btnMore:setTitleText(getLocStr("btn_text_more"));
end

-- 注册事件处理回调函数
function UIGameBoard:registerEventCallback()
    -- 界面析构后，需要清理下
    self:registerScriptHandler(function(ev)
        if ev == "exit" then
            cclog("UIGameBoard 界面析构清理");
            if _G["gameScene"] then
                return;
            end
            EventMgr.removeAll("UIGameBoard");
            -- 重绘一下
            local uiSystemSetting = UIMgr.getCurrentScene():getFormByName("UISystemSetting");
            if uiSystemSetting then
                uiSystemSetting:redraw();
            end

            -- 游戏外公告，需要执行自动更新
            if type(self.boardId) == "number" and self.boardId == 0 then
                local uiLogin = UIMgr.getCurrentScene():getFormByName("UILogin");
                if uiLogin then
                    -- 开始自动更新
                    clearMyRequire();
                    enterAutoPatchScene();
                end
            end
        elseif ev == "enter" then

        end
    end);
end

-- 适配
function resize(node)
    -- bg居中显示并充满整个屏
    AlignM.fitToScreen(node, "bg");

    -- CT居中并缩放至合适大小
    AlignM.alignToCenter(node, "CT");

    -- BT置于底部并缩放至合适大小
    AlignM.alignToBottomCenter(node, "BT");
end

-- 添加特殊节点
function UIGameBoard:addSpecialNode()
    local data = self.data;
    if type(data["activity"]) ~= "table" then
        return nil;
    end

    local node = self:activityNode(data);
    return node;
end

-- 活动特殊节点
function UIGameBoard:activityNode(data)
    -- 活动冈布奥对话节点
    local activityNode = cc.CSLoader:createNode("layout/setting/game_board/ActivityPet.csb");

    -- 绘制冈布奥
    local info = data["activity"];
    local petNode = findChildByName(activityNode, "pet");
    local headImg = findChildByName(petNode, "img_node");
    local modelNode = findChildByName(petNode, "model_node");
    local petId = info["pet_id"] or 1;
    local modelId = PetM.query(petId, "default_model");
    local petModelConfig = PetM.queryModel(modelId);
    local iconPath = getHeroIconPath(petModelConfig["icon"]);
    local scale = petModelConfig["model_scale"] * 1.5;
    local offsetX = petModelConfig["offset_x"];
    local offsetY = petModelConfig["offset_y"];

    -- 如果有模型就创建没有，没有就使用静态图片
    self.modelNode = createHeroModel(modelId, headImg, modelNode,
        scale, iconPath,offsetX, offsetY);

    -- 点击
    local panel = findChildByName(petNode, "panel");
    local function onModelClick(sender, eventType)
        if eventType == ccui.TouchEventType.ended then
            require "game/ui/form/hero/UIHeroDetailInfo";
            UIMgr.getCurrentScene():removeFormByName("UIHeroDetailInfo");
            uiGoodsDetail = UIHeroDetailInfo.create(petId, "activity");
            UIMgr.getCurrentScene():addForm(uiGoodsDetail);
        end
    end
    panel:addTouchEventListener(onModelClick);
    panel:setTouchEnabled(true);

    -- 冈布奥发言
    self:activityTalk(activityNode, data);

    return activityNode;
end

-- 倒计时格式
function UIGameBoard:leftTimeStr(leftTime, type)
    if type == "open" then
        -- 开启的格式
        local days = math.floor(leftTime / (3600 * 24));
        local hours = math.floor(leftTime / 3600 - days * 24);
        local mins = math.ceil(leftTime / 60) - days * 24 * 60 - hours * 60;
        return string.format(getLocStr("activate_open_time"), days, hours, mins);
    else
        -- 距离结束的格式
        if leftTime > 3600 then
            return math.floor(leftTime/3600) .. "h";
        elseif leftTime > 60 then
            return math.floor(leftTime/60) .. "m";
        end
        return math.floor(leftTime) .. "s";
    end
    return "";
end

-- 活动冈布奥发言
function UIGameBoard:activityTalk(node, data)
    local dialogNode = findChildByName(node, "dialog");
    local textLabel = findChildByName(dialogNode, "panel/text");

    local info = data["activity"];
    local openTime = info["open_time"];
    local endTime = openTime + info["last_hour"] * 3600;

    local function tick()
        local curTime = TimeM.getServerTime();
        if openTime >= curTime then
            -- 还未开始
            local timeStr = self:leftTimeStr(openTime - curTime, "open");
            self.msg = string.format(getLocStr("activity_open_content"), timeStr, info["last_hour"]);
        elseif endTime > curTime then
            -- 已经开始
            local timeStr = self:leftTimeStr(endTime - curTime);
            self.msg = string.format(getLocStr("activity_end_content"), timeStr);
        else
            -- 已经结束了
            -- 关闭自身界面/弹字提示
            UIMgr.getCurrentScene():removeFormByName("UIGameBoard");
            -- 抛一下公告界面重绘
            EventMgr.fire(event.BOARDS_UPDATE);
            alert(getLocStr("activity_is_over"));
            return;
        end

        TextStyleM.setTextStyle(textLabel, TextStyleM.TEXT_SIZE_SMALL2, TextStyleM.TEXT_COLOR_DARK_BROWN, false, nil, nil, nil, nil, TextStyleM.TEXT_SIZE_SMALL);
        textLabel = applyString(textLabel, self.msg);

        performWithDelay(self.node, tick, 1);
    end

    tick();

    self.textLabel = textLabel;

    -- 收集字符列表
    self:collectLetters(self.msg);

    dialogNode:setScale(0.01);
    dialogNode:setVisible(true);

    local scaleTo = cc.ScaleTo:create(0.3, 1);
    local callFunc = cc.CallFunc:create(function ()
            self:playTextEffect()
        end);
    dialogNode:runAction(cc.Sequence:create(scaleTo, callFunc));
end

-- 对话效果，一个字一个字慢慢播放
function UIGameBoard:playTextEffect()
    local function play()
        if #self.letters > 0 then
            local letter = self.letters[#self.letters];
            table.remove(self.letters, #self.letters);
            local fadeIn = cc.FadeIn:create(0.1);
            local callFunc = cc.CallFunc:create(function()
                if 0 == #self.letters then
                    -- 标记字体播放完成
                    self.isFinished = true;
                end
            end);

            self.isFinished = false;
            letter:runAction(cc.Sequence:create(fadeIn, callFunc));
            performWithDelay(self.textLabel, play, 0.01);
        end
    end

    play();
end

-- 收集字符列表
function UIGameBoard:collectLetters(text)
    local textLabel = self.textLabel;

    local count = string.getWCharCount(text);
    self.letters = {};

    local i = 0;
    local endPos = count - 1;
    local charPos = 0;
    local curPaddingCount = 0;
    while i <= endPos do
        local letter = textLabel:getVirtualRenderer():getLetter(i);
        local nextLetter = textLabel:getVirtualRenderer():getLetter(i+1);
        if letter then
            -- 初始所有字符置为不可见
            letter:setOpacity(0);

            -- 加入到字符列表
            table.insert(self.letters, 1, letter);
        else
            if nextLetter ~= nil and not string.isBreakLineChar(text, charPos-curPaddingCount) then
                -- 如果是系统自动添加的换行符，需要把结束位置往后挪
                endPos = endPos + 1;
                curPaddingCount = curPaddingCount + 1;
            end
        end

        i = i + 1;
        charPos = charPos + 1;
    end
end